﻿using Prism.Events;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Interop;
using VirtualBank.Common.Events;

namespace VirtualBank.Common.Entity
{
    public enum BankState
    {
        CLOSE,
        OPEN
    }

    public class Bank
    {
        Dictionary<string, BankAccount> AccountDictionary = new Dictionary<string, BankAccount>();
        List<string> ClientList = new List<string>();

        ConcurrentQueue<RequireMsg> RequireMsgs = new ConcurrentQueue<RequireMsg>();
        ConcurrentQueue<AccountInfoMsg> AccountInfoMsgs = new ConcurrentQueue<AccountInfoMsg>();

        BankState m_State=BankState.CLOSE;

        IEventAggregator m_EventAggregator;

        public Bank(IEventAggregator ea)
        {
            m_EventAggregator = ea;
            Init();
        }

        private void Init()
        {
            m_State = BankState.OPEN;
            m_EventAggregator.GetEvent<RequireEvent>().Subscribe(RequireMsgReceive);
            m_EventAggregator.GetEvent<QueryAccountEvent>().Subscribe(QueryAccount);
            m_EventAggregator.GetEvent<LoginEvent>().Subscribe(Login);
            for(int i=1; i < 6; i++)
            {
                string id = i.ToString().PadLeft(6, '0');
                BankAccount account = new BankAccount(id);
                account.InfoTrans += AccountMsgReceive;
                AccountDictionary.Add(id,account);
            }
            Task.Factory.StartNew(RequireMsgQueueHandler);
            Task.Factory.StartNew(AccountInfoMsgQueueHandler);
        }

        private void RequireMsgQueueHandler()
        {            
            while (true)
            {
                RequireMsg msg;
                if (RequireMsgs.TryDequeue(out msg))
                {
                    AccountDictionary[msg.Id].RequireService(msg.Msg);
                }
                //Thread.Sleep(10);
            }
        }

        private void AccountInfoMsgQueueHandler()
        {
            while (true)
            {
                AccountInfoMsg msg;
                if (AccountInfoMsgs.TryDequeue(out msg))
                {
                    m_EventAggregator.GetEvent<AccountInfoEvent>().Publish(msg);
                }
                //Thread.Sleep(10);
            }
        }

        private void RequireMsgReceive(RequireMsg msg)
        {
            if(m_State == BankState.OPEN)
                RequireMsgs.Enqueue(msg);
        }

        private void AccountMsgReceive(AccountInfoMsg msg)
        {
            if (m_State == BankState.OPEN)
                AccountInfoMsgs.Enqueue(msg);
        }

        private void QueryAccount(string id)
        {
            BankAccount account = AccountDictionary[id];
            AccountInfoMsg msg = account.CheckAccountState();
            if (m_State == BankState.OPEN)
                m_EventAggregator.GetEvent<AccountInfoEvent>().Publish(msg);
        }

        private void Login(LoginMsg msg)
        {
            bool result = false;
            if(AccountDictionary.ContainsKey(msg.ID))
            {
                result = true;
            }
            ClientList.Add(msg.ID);
            m_EventAggregator.GetEvent<LoginResultEvent>().Publish(result);
        }

        public void Close()
        {
            foreach(var item in ClientList)
            {
                m_EventAggregator.GetEvent<BankCloseEvent>().Publish(item);
            }
        }
    }
}
